Imports Microsoft.Practices.EnterpriseLibrary.Data.Sql
Imports Microsoft.Practices.EnterpriseLibrary.Data

Imports system.Configuration.Provider
Imports System.Data.SqlClient
Imports System.Diagnostics

Namespace Seuss.EnterpriseLibrary.Membership

    Public Class SeussRoleProvider
        Inherits RoleProvider

#Region "Variables"
        Private _eventSource As String = "SQLRoleProvider"
        Private _eventLog As String = "Application"
        Private _exceptionMessage As String = "Una excepcion a ocurrido. Por favor verifique el log."

        Private _ConnectionStringSettings As ConnectionStringSettings
        Private _ConnectionString As String
        Private _WriteExceptionsToEventLog As Boolean = False
        Private _ApplicationName As String
#End Region

#Region "Metodos Sobrecargados"

        Property WriteExceptionsToEventLog() As Boolean
            Get
                Return _WriteExceptionsToEventLog
            End Get
            Set(ByVal value As Boolean)
                _WriteExceptionsToEventLog = value
            End Set
        End Property

        Public Overrides Sub AddUsersToRoles(ByVal usernames() As String, ByVal roleNames() As String)
            Throw New NotSupportedException("No se permiten asignaciones de rol.")
        End Sub

        Public Overrides Property ApplicationName() As String
            Get
                Return _ApplicationName
            End Get
            Set(ByVal value As String)
                _ApplicationName = value
            End Set
        End Property

        Public Overrides Sub CreateRole(ByVal roleName As String)
            Throw New NotSupportedException("No se permiten crear roles.")
        End Sub

        Public Overrides Function DeleteRole(ByVal roleName As String, ByVal throwOnPopulatedRole As Boolean) As Boolean
            Throw New NotSupportedException("No se permite eliminar roles.")
        End Function

        Public Overrides Function FindUsersInRole(ByVal roleName As String, ByVal usernameToMatch As String) As String()
            Dim tmpUserNames As String = ""

            Try
                Dim db As Database = DatabaseFactory.CreateDatabase(_ConnectionString)
                Using Cmd As SqlCommand = db.GetStoredProcCommand("sp_Rol_Get")
                    db.AddInParameter(Cmd, "@cPerUsuCodigo", System.Data.DbType.String, usernameToMatch)
                    db.AddInParameter(Cmd, "@cRolNombre", System.Data.DbType.String, roleName)
                    Using Reader As SqlDataReader = db.ExecuteReader(Cmd)
                        While (Reader.Read)
                            tmpUserNames &= Reader.GetString(0) & ","
                        End While
                    End Using
                End Using
            Catch ex As SqlException
                If _WriteExceptionsToEventLog Then
                    WriteToEventLog(ex, "FindUsersInRole")
                Else
                    Throw ex
                End If
            End Try

            If (tmpUserNames.Length > 0) Then
                ' Remove trailing comma.
                tmpUserNames = tmpUserNames.Substring(0, tmpUserNames.Length - 1)
                Return tmpUserNames.Split(",")
            End If
            Dim StrOut() As String = {(String.Empty)}
            Return StrOut
        End Function

        Public Overrides Function GetAllRoles() As String()
            Dim tmpRoleNames As String = String.Empty

            Try
                Dim db As Database = DatabaseFactory.CreateDatabase(_ConnectionString)
                Using Cmd As SqlCommand = db.GetStoredProcCommand("sp_Rol_Get")
                    db.AddInParameter(Cmd, "@cPerUsuCodigo", System.Data.DbType.String, DBNull.Value)
                    Dim reader As SqlDataReader = db.ExecuteReader(Cmd)
                    While reader.Read
                        tmpRoleNames &= reader.GetString(0) & ","
                    End While
                End Using
            Catch ex As SqlException
                If _WriteExceptionsToEventLog Then
                    WriteToEventLog(ex, "GetAllRoles")
                Else
                    Throw ex
                End If
            End Try

            If (tmpRoleNames.Length > 0) Then
                ' Remove trailing comma.
                tmpRoleNames = tmpRoleNames.Substring(0, tmpRoleNames.Length - 1)
                Return tmpRoleNames.Split(",")
            End If
            Dim StrOut() As String = {(String.Empty)}
            Return StrOut
        End Function

        Public Overrides Function GetRolesForUser(ByVal username As String) As String()
            ' Validate input parameters
            If String.IsNullOrEmpty(username) Then
                Throw New ArgumentNullException()
            End If

            Dim tmpRoleNames As String = String.Empty

            Try
                Dim db As Database = DatabaseFactory.CreateDatabase(_ConnectionString)
                Using Cmd As SqlCommand = db.GetStoredProcCommand("sp_Rol_Get")
                    db.AddInParameter(Cmd, "@cPerUsuCodigo", System.Data.DbType.String, username)
                    Dim reader As SqlDataReader = db.ExecuteReader(Cmd)
                    While reader.Read
                        tmpRoleNames &= reader.GetString(0) & ","
                    End While
                End Using
            Catch ex As SqlException
                If _WriteExceptionsToEventLog Then
                    WriteToEventLog(ex, "GetRolesForUser")
                Else
                    Throw ex
                End If
            End Try

            If (tmpRoleNames.Length > 0) Then
                ' Remove trailing comma.
                tmpRoleNames = tmpRoleNames.Substring(0, tmpRoleNames.Length - 1)
                Return tmpRoleNames.Split(",")
            End If
            Dim StrOut() As String = {(String.Empty)}
            Return StrOut


        End Function

        Public Overrides Function GetUsersInRole(ByVal roleName As String) As String()
            Throw New NotSupportedException("No se permite brindar la lista de Usuarios en un rol")
        End Function

        Public Overrides Function IsUserInRole(ByVal username As String, ByVal roleName As String) As Boolean

            ' Validate input parameters
            If username Is Nothing OrElse roleName Is Nothing Then
                Throw New ArgumentNullException()
            End If
            If username = String.Empty OrElse roleName = String.Empty Then
                Throw New ArgumentException()
            End If

            Dim userIsInRole As Boolean = False

            Try
                Dim db As Database = DatabaseFactory.CreateDatabase(_ConnectionString)
                Using Cmd As SqlCommand = db.GetStoredProcCommand("sp_Rol_Get")
                    db.AddInParameter(Cmd, "@cPerUsuCodigo", System.Data.DbType.String, username)
                    db.AddInParameter(Cmd, "@cRolNombre", System.Data.DbType.String, roleName)
                    Using reader As SqlDataReader = db.ExecuteReader(Cmd)
                        userIsInRole = reader.HasRows
                    End Using
                End Using
            Catch ex As SqlException
                If _WriteExceptionsToEventLog Then
                    WriteToEventLog(ex, "IsUserInRole")
                Else
                    Throw ex
                End If
            End Try

            Return userIsInRole
        End Function

        Public Overrides Sub RemoveUsersFromRoles(ByVal usernames() As String, ByVal roleNames() As String)
            Throw New NotSupportedException("No se puede retirar un usuario de un rol.")
        End Sub

        Public Overrides Function RoleExists(ByVal roleName As String) As Boolean
            ' Validate input parameters
            If roleName Is Nothing Then
                Throw New ArgumentNullException()
            End If
            If roleName = String.Empty Then
                Throw New ArgumentException()
            End If

            Dim exists As Boolean = False

            Try
                Dim db As Database = DatabaseFactory.CreateDatabase(_ConnectionString)
                Using Cmd As SqlCommand = db.GetStoredProcCommand("sp_Rol_Get")
                    db.AddInParameter(Cmd, "@cRolNombre", System.Data.DbType.String, roleName)
                    Using reader As SqlDataReader = db.ExecuteReader(Cmd)
                        exists = reader.HasRows
                    End Using
                End Using
            Catch ex As SqlException
                If _WriteExceptionsToEventLog Then
                    WriteToEventLog(ex, "RoleExists")
                Else
                    Throw ex
                End If
            End Try
            Return exists
        End Function

        ' RoleProvider methods
        Public Overrides Sub Initialize(ByVal name As String, _
                                ByVal config As NameValueCollection)
            ' Verify that config isn't null
            If config Is Nothing Then
                Throw New ArgumentNullException("config")
            End If

            ' Assign the provider a default name if it doesn't have one
            If String.IsNullOrEmpty(name) Then
                name = "SQLRoleProvider"
            End If

            ' Add a default "description" attribute to config if the
            ' attribute doesn't exist or is empty
            If String.IsNullOrEmpty(config("description")) Then
                config.Remove("description")
                config.Add("description", "Sample SQL Role provider")
            End If

            ' Call the base class's Initialize method
            MyBase.Initialize(name, config)

            If config("applicationName") Is Nothing OrElse String.IsNullOrEmpty(config("applicationName")) Then
                _ApplicationName = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath
            Else
                _ApplicationName = config("applicationName")
            End If


            If Not String.IsNullOrEmpty(config("writeExceptionsToEventLog")) Then
                If config("writeExceptionsToEventLog").ToUpper() = "TRUE" Then
                    _WriteExceptionsToEventLog = True
                End If
            End If

            ' Inicializa la cadena de conexion

            _ConnectionStringSettings = ConfigurationManager.ConnectionStrings(config("connectionString"))

            If _ConnectionStringSettings Is Nothing OrElse String.IsNullOrEmpty(_ConnectionStringSettings.ConnectionString.Trim) Then
                Throw New ProviderException("La cadena de conexion no puede estar en blanco.")
            End If

            _ConnectionString = _ConnectionStringSettings.Name


        End Sub

#End Region

#Region "Funciones de ayuda"

        'WriteToEventLog: Write to Web Server Log 
        Private Sub WriteToEventLog(ByVal e As Exception, ByVal action As String)

            Dim log As EventLog = New EventLog()
            log.Source = _eventSource
            log.Log = _eventLog

            Dim message As String = "An exception occurred communicating with the data source." & vbCrLf & vbCrLf
            message &= "Action: " & action & vbCrLf & vbCrLf
            message &= "Exception: " + e.ToString()

            log.WriteEntry(message)
        End Sub

#End Region

    End Class

End Namespace